package com.base;

import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

/**
 *  主要针对 HashMap 和 ConcurrentHashMap 的实现原理
 *
 * @author Jinx
 * @date 2021/6/7 9:53
 */
public class MapExplore {

    public static void main(String[] args) throws Exception {
        // 左移就是乘以2  右移就除以2
        System.out.println(1 << 3);

        /*
         * NAN 表示一种未定义或无法表示的值   NAN == NAN :false 无法比较  请看：java/lang/Float.java:69
         * 如果用 Float 的 equals 比较则为true，因为Float重写了equals，将其转成了一个值来比较。
         */
        System.out.println(Float.NaN);


        // 通过反射调其内部方法窥视其原理
        Class<?> clazz = HashMap.class;
        Method tableSizeFor = clazz.getDeclaredMethod("tableSizeFor", int.class);
        tableSizeFor.setAccessible(true);
        System.out.println(tableSizeFor.invoke(null, 5));
    }




    @SuppressWarnings("all")
    private void hashMapExplore(){
        /*
         *  初始化过程(针对传入容量这个构造函数)：
         *  1. 校验参数合法性
         *  2. 初始化 负载因子（用的默认的 0.75）
         *  3. 初始化map的初始容量 （最近的2的指数幂）
         *
         * @see HashMap#tableSizeFor(int)  初始化容量算法，会计算出和传入容量相近的2的指数幂容量并取大的那一个。eg：传入10 会返回16
         */
        Map<String, Object> map = new HashMap<>(16);

        /**
         *  put方法第一次存储过程：
         *  1. 先计算出key的hash值
         *  2. 定义了四个临时变量  tab：指向当前内部数组  p：  n：当前数组的长度  i：
         *  2. 如果tab为空，说明当前数组还未初始化，调用resize()初始化数组，并让tab指向这个新数组，n等于当前tab的长度。
         *  3. 根据 hash & n-1 确定数组角标，因为第一次肯定为空，直接插入元素。
         *  4. 成员变量 modCount 加1， 成员变量 size +1，如果此时size > 阈值，则会进行resize()扩容，这里第一次不会。
         *  5. 调用 afterNodeInsertion()， hashMap空实现，无作用。
         *
         *
         * @see HashMap#hash(Object)  计算hash算法，如果key为空返回0，不为空用key的hashcode 异或 它的hashcode无符号右移16位。
         * @see HashMap#resize()  初始化或者扩容方法，返回新数组。初始化：长度设置为默认长度16，阈值设置为 0.75 * 16，new完新数组后返回。
         * @see HashMap#modCount  结构被修改次数，作用目前未知。
         * @see HashMap#size  当前已存入的k-v数量
         * @see HashMap#afterNodeInsertion(boolean)  空实现，linkedHashMap有实现，估计是拿来记录顺序的。
         */
        map.put("jinx", "jinx is the coolest man");


        /**
         *  get方法第一次获取过程：
         *
         */
        map.get("jinx");


    }

}
